﻿


namespace AllServer.Core;

public class RequestAuditFilter : IAsyncActionFilter
{
    private readonly ILogger<RequestAuditFilter> _logger;

    public RequestAuditFilter(ILogger<RequestAuditFilter> logger)
    {
        _logger = logger;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        //============== 这里是执行方法之前获取数据 ====================

        // 获取控制器、路由信息
        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        // 获取 HttpContext 和 HttpRequest 对象
        var httpContext = context.HttpContext;

        string url = $"{httpContext.Request.Host}{httpContext.Request.Path}{httpContext.Request.QueryString}";

        // 获取客户端 IPv4 地址
        var remoteIPv4 = IpHelper.GetClientUserIp();

        // 请求时间
        var requestedTime = DateTimeOffset.Now;

        // 获取请求参数（写入日志，需序列化成字符串后存储）
        var parameterValues = context.ActionArguments;

        //============== 这里是执行方法之后获取数据 ====================
        // 计算接口执行时间
        var timeOperation = Stopwatch.StartNew();
        var actionContext = await next();
        timeOperation.Stop();

        // 获取返回的结果
        var returnResult = actionContext.Result;

        object returnValue = null;
        // 解析返回值
        if (CheckVaildResult(returnResult, out var data))
        {
            returnValue = data;
        }

        // 判断是否请求成功，没有异常就是请求成功
        var isRequestSucceed = actionContext.Exception == null;

        //大数据返回不记录
        if (url.IndexOf("GlobalCountry/GetList") != -1)
        {
            return;
        }
        var json = new
        {
            Url = url,
            Method = httpContext.Request.Method,
            Parameters = parameterValues,
            Result = returnValue,
            Elapsed = timeOperation.ElapsedMilliseconds,
            Ip = remoteIPv4
        };
        string str = JsonConvert.SerializeObject(json);
        _logger.LogInformation(str);

        ////============== 这里是执行方法之前获取数据 ====================

        //// 获取控制器、路由信息
        //var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        //// 获取请求的方法
        //var method = actionDescriptor.MethodInfo;

        //// 获取 HttpContext 和 HttpRequest 对象
        //var httpContext = context.HttpContext;
        //var httpRequest = httpContext.Request;

        //// 获取客户端 Ipv4 地址
        //var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();

        //// 获取请求的 Url 地址
        //var requestUrl = httpRequest.GetRequestUrlAddress();

        //// 获取来源 Url 地址
        //var refererUrl = httpRequest.GetRefererUrlAddress();

        //// 获取请求参数（写入日志，需序列化成字符串后存储）
        //var parameters = context.ActionArguments;

        //// 获取操作人（必须授权访问才有值）"userId" 为你存储的 claims type，jwt 授权对应的是 payload 中存储的键名
        //var userId = httpContext.User?.FindFirstValue("userId");

        //// 请求时间
        //var requestedTime = DateTimeOffset.Now;


        ////============== 这里是执行方法之后获取数据 ====================
        //var actionContext = await next();

        //// 获取返回的结果
        //var returnResult = actionContext.Result;

        //// 判断是否请求成功，没有异常就是请求成功
        //var isRequestSucceed = actionContext.Exception == null;

        //// 获取调用堆栈信息，提供更加简单明了的调用和异常堆栈
        //var stackTrace = EnhancedStackTrace.Current();

        //// 这里写入日志，或存储到数据库中！！！~~~~~~~~~~~~~~~~~~~~
    }

    /// <summary>
    /// 检查是否是有效的结果（可进行规范化的结果）
    /// </summary>
    /// <param name="result"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    internal static bool CheckVaildResult(IActionResult result, out object data)
    {
        data = default;

        // 排除以下结果，跳过规范化处理
        var isDataResult = result switch
        {
            ViewResult => false,
            PartialViewResult => false,
            FileResult => false,
            ChallengeResult => false,
            SignInResult => false,
            SignOutResult => false,
            RedirectToPageResult => false,
            RedirectToRouteResult => false,
            RedirectResult => false,
            RedirectToActionResult => false,
            LocalRedirectResult => false,
            ForbidResult => false,
            ViewComponentResult => false,
            PageResult => false,
            NotFoundResult => false,
            NotFoundObjectResult => false,
            _ => true,
        };

        // 目前支持返回值 ActionResult
        if (isDataResult) data = result switch
        {
            // 处理内容结果
            ContentResult content => content.Content,
            // 处理对象结果
            ObjectResult obj => obj.Value,
            // 处理 JSON 对象
            JsonResult json => json.Value,
            _ => null,
        };

        return isDataResult;
    }
}
